package com.s7175.kor.gui.queries;

import java.util.Collection;
import java.util.Iterator;
import java.util.Vector;

import pl.wcislo.sbql4j.java.model.runtime.Struct;

import javax.swing.table.*;

import com.s7175.kor.model.ModelMaster;

@SuppressWarnings("serial")
public class QueryTableModel extends AbstractTableModel {
	private Vector<String[]> cache;
	private int colCount;
	private String[] headers;

	public QueryTableModel() {
		cache = new Vector<String[]>();
	}

	public String getColumnName(int i) {
		return headers[i];
	}

	public int getColumnCount() {
		return colCount;
	}

	public int getRowCount() {
		return cache.size();
	}

	public Object getValueAt(int row, int col) {
		return ((String[]) cache.elementAt(row))[col];
	}

	public void setQuery(Collection<Struct> meta) {
		cache = new Vector<String[]>();
		try {;
			colCount = -1;
			Iterator<Struct> rs = meta.iterator();
			
			while (rs.hasNext()) {
				Struct singleStruct = rs.next();
				if(colCount == -1){
					colCount = getNumberOfColumn(singleStruct);
					headers = new String[colCount];
					getHeaders(singleStruct,0);
					//System.out.println("Liczba kolumn to: " + colCount);
				}
				String[] record = new String[colCount];
				getContent(singleStruct,record,0);
				//System.out.println(Arrays.toString(record));
				/*
				 * for (int i=0; i < colCount; i++) { record[i] = rs.next(); }
				 */
				cache.addElement(record);
			}
			
			//System.out.println(Arrays.toString(headers));
			/*for (int h = 0; h < colCount; h++) {
				headers[h] = "Header_" + h;
			}*/

			fireTableChanged(null); // notify everyone that we have a new table.
		} catch (Exception e) {
			cache = new Vector<String[]>(); // blank it out and keep going.
			e.printStackTrace();
		}
	}

	public void setQuery(Struct singleStruct) {
		cache = new Vector<String[]>();
		try {;
			colCount = -1;
			if(colCount == -1){
				colCount = getNumberOfColumn(singleStruct);
				headers = new String[colCount];
				getHeaders(singleStruct,0);
				//System.out.println("Liczba kolumn to: " + colCount);
			}
			String[] record = new String[colCount];
			getContent(singleStruct,record,0);
			cache.addElement(record);

			fireTableChanged(null); // notify everyone that we have a new table.
		} catch (Exception e) {
			cache = new Vector<String[]>(); // blank it out and keep going.
			e.printStackTrace();
		}
	}
	
	private int getNumberOfColumn(Struct rs){
		int tmp = 0;
		for(Object oSingle: rs.values()){
			if(oSingle instanceof ModelMaster || oSingle instanceof String || oSingle instanceof Number || oSingle instanceof Boolean || oSingle instanceof Collection<?>){
				++tmp;
			}else{
				tmp += getNumberOfColumn((Struct)oSingle);
			}
		}		
		return tmp;
	}
	
	private int getContent(Struct rs, String[] record, int actualPosition) {
		for(Object oSingle: rs.values()){
			if(oSingle instanceof ModelMaster || oSingle instanceof String || oSingle instanceof Number || oSingle instanceof Boolean || oSingle instanceof Collection<?>){
				record[actualPosition] = oSingle.toString();
				++actualPosition;
			}else{
				actualPosition += getContent((Struct)oSingle,record,actualPosition);	
			}
		}
		return actualPosition;
	}
	
	private int getHeaders(Struct rs, int actualPosition) {
		for(Object oKey: rs.keySet()){
			Object oSingle = rs.get(oKey);
			if(oSingle instanceof ModelMaster){
				//jest ktoryms z moich modeli danych
				boolean bIsNumber;
				//sprawdzam czy jest liczba
				try{
					Integer.parseInt((String) oKey);
					bIsNumber = true;
				}catch(Exception ex){
					bIsNumber = false;
				}
				//jesli jest liczba, czyli mamy standarowego nienazwanego structa, czyli hederem tabeli bedzie prosta nazwa klasy mojego modelu
				//jezeli zas liczba nie jest, to wtedy headerem jest ten klucz
				headers[actualPosition] = bIsNumber ? oSingle.getClass().getSimpleName() : (String)oKey;
				++actualPosition;
			}else if(oSingle instanceof String || oSingle instanceof Number || oSingle instanceof Boolean || oSingle instanceof Collection<?>){
				headers[actualPosition] = oKey.toString();
				++actualPosition;
			}else{
				actualPosition += getHeaders((Struct)oSingle,actualPosition);				
			}
		}
		return actualPosition;
	}
}